package bloggo

import (
	"crypto/md5"
	"database/sql/driver"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"net/smtp"
	"runtime"
	"strings"
	"time"
)

const (
	PROVINCE = "省"
	CITY     = "市"
	UNKNOWN  = "未知"
)

type IPSource struct {
	Country   string `json:"country"`
	ShortName string `json:"shortName"`
	Province  string `json:"province"`
	City      string `json:"city"`
	Area      string `json:"area"`
	Isp       string `json:"isp"`
	Net       string `json:"net"`
	Ip        string `json:"ip"`
	Code      int    `json:"code"`
	Desc      string `json:"desc"`
}

// Time 自定义时间
type Time time.Time

const TimeFormat = "2006-01-02T15:04:05"

func (t *Time) UnmarshalJSON(data []byte) error {
	if string(data) == "null" {
		return nil
	}
	var err error
	//前端接收的时间字符串
	str := string(data)
	//去除接收的str收尾多余的"
	timeStr := strings.Trim(str, "\"")
	t1, err := time.Parse(TimeFormat, timeStr)
	*t = Time(t1)
	return err
}

func (t Time) MarshalJSON() ([]byte, error) {
	formatted := fmt.Sprintf("\"%v\"", time.Time(t).Format(TimeFormat))
	return []byte(formatted), nil
}

func (t Time) Value() (driver.Value, error) {
	// Time 转换成 time.Time 类型
	tTime := time.Time(t)
	return tTime.Format(TimeFormat), nil
}

func (t *Time) Scan(v interface{}) error {
	switch vt := v.(type) {
	case time.Time:
		// 字符串转成 time.Time 类型
		*t = Time(vt)
	default:
		return errors.New("类型处理错误")
	}
	return nil
}

func (t *Time) String() string {
	return fmt.Sprintf("hhh:%s", time.Time(*t).String())
}

// GetIpAddress returns request real ip.
func GetIpAddress(r *http.Request) (string, error) {
	ip := r.Header.Get("X-Real-IP")
	if net.ParseIP(ip) != nil {
		return ip, nil
	}

	ip = r.Header.Get("X-Forward-For")
	for _, i := range strings.Split(ip, ",") {
		if net.ParseIP(i) != nil {
			return i, nil
		}
	}

	ip, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		return "", err
	}

	if net.ParseIP(ip) != nil {
		return ip, nil
	}

	return "", errors.New("no valid ip found")
}

// GetIpSource 获取ip信息
func GetIpSource(ipAddress string) (*IPSource, error) {
	var data IPSource
	res, err := http.Get("https://ip.useragentinfo.com/json?ip=" + ipAddress)
	defer func() {
		err := res.Body.Close()
		if err != nil {
			Log(err.Error())
		}
	}()
	if err != nil {
		return nil, err
	}
	bytes, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal(bytes, &data)
	if err != nil {
		return nil, err
	}
	if data.Code == 200 {
		return &data, nil
	}
	return &data, errors.New(data.Desc)
}

func MD5(data []byte) string {
	has := md5.Sum(data)
	md5str := fmt.Sprintf("%x", has) //将[]byte转成16进制
	return md5str
}

// SendPlainMail 发送文本格式邮件
func SendPlainMail(subject, msg string, toMails []string) error {
	auth := smtp.PlainAuth("", Conf.Mail.Username, Conf.Mail.Password, Conf.Mail.Host)
	data := []byte(fmt.Sprint("From:", Conf.Mail.Username, "\r\nSubject: ", subject, "\r\nContent-Type: text/plain; charset=UTF-8\r\n\r\n", msg))
	return smtp.SendMail(Conf.Mail.Host+":"+Conf.Mail.Port, auth, Conf.Mail.Username, toMails, data)
}

// FetchFuncName 提取当前正在执行的函数名
func FetchFuncName() string {
	pc, _, _, _ := runtime.Caller(1)
	funcName := runtime.FuncForPC(pc).Name()
	fmt.Println(funcName)
	split := strings.Split(funcName, ".")
	return split[len(split)-1]
}
